#include "../include/SocketIO.hpp"

#include <sys/socket.h>
#include <errno.h>
#include <stdio.h>

namespace cdm{

SocketIO::SocketIO(int fd)
:_fd(fd){
}



int SocketIO::sendN(const char*buff,int len){
    int slen = len;
    const char *pbuf = buff;
    while(slen > 0){
        int ret = send(_fd,pbuf,slen,0);
        if(ret < 0){
            perror("send");
            return ret;
        }else{
            slen -= ret;
            pbuf += ret;
        }
    }
    return slen;
}

int SocketIO::recvN(char*buff,int len){
    int recvlen = len;
    char *pbuf =buff;
    while(recvlen > 0){
        int ret = recv(_fd,pbuf,len,0);
        if(ret == -1 && errno == EINTR){
            continue;
        }else if(ret ==-1){
            perror("recv");
            return ret;
        }else if(ret == 0){
            return len - recvlen;
        }
        recvlen -= ret;
        pbuf += ret;
    }
    return recvlen;
}

int SocketIO::readPacket(Packet &packet){
    int type,length;
    recvN((char*)&type,sizeof(type));
    recvN((char*)&length,sizeof(length));
    if(length > 0){
        char *buff = new char[length+1]();
        recvN(buff,length);
        packet._type = type;
        packet._length = length;
        packet._msg.assign(buff,length);
        delete []buff;
        return length + 8;
    }
    return 8;
}

int SocketIO::readLine(char*buff,int max){
    int recved =0;
    char *pbuf = buff;
    int ret = recvPeek(buff,max);
    while(recved <= max){
        //读取到换行符
        for(int i = 0;i < ret;i++){
            if(pbuf[i] =='\n' ){
                ret = recvN(pbuf,i+1); 
                recved = i + 1;
                return recved;
            }
        }
        //未读取到换行符
        ret = recvN(pbuf,ret);
        recved += ret;
        pbuf += ret;
    }
    return recved;//返回接收字符数量
}

int SocketIO::recvPeek(char *buff,int max){

    int ret = 0;
    do{
       ret = recv(_fd,buff,max,MSG_PEEK);
    }while(ret == -1 && errno == EINTR);
    if(ret < -1){
        perror("recv");
    }
    return  ret;
}


}//end of namespace


